package com.istock.user.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.istock.base.common.api.model.ApiBaseResponse;
import com.istock.base.common.api.model.PageInfo;
import com.istock.base.common.api.model.RetStatusEnum;
import com.istock.base.enumration.Enums;
import com.istock.base.export.util.DataTranslateUtils;
import com.istock.base.serializer.JsonSerializer;
import com.istock.base.serializer.json.JsonSerializerFactory;
import com.istock.union.user.client.SSOClientUtils;
import com.istock.union.user.model.Constants;
import com.istock.union.user.model.CredentialEditVO;
import com.istock.union.user.model.DeptInfo;
import com.istock.union.user.model.OperLog;
import com.istock.union.user.model.RoleInfo;
import com.istock.union.user.model.RoleInfoQueryModel;
import com.istock.union.user.model.SSOUser;
import com.istock.union.user.model.SecurityChecker;
import com.istock.union.user.model.UpdatePasswordModel;
import com.istock.union.user.model.UserInfo;
import com.istock.union.user.model.UserInfoQueryModel;
import com.istock.union.user.model.ext.UserInfoVO;
import com.istock.union.user.service.DeptInfoService;
import com.istock.union.user.service.RoleInfoService;
import com.istock.union.user.service.UserCredentialInfoService;
import com.istock.union.user.service.UserInfoService;
import com.istock.union.user.translate.TenantTranslateCallback;

@RequestMapping("/s/userInfo")
@Controller
public class UserInfoController {

	private static final Logger logger = LoggerFactory.getLogger(UserInfoController.class);
	
	@Autowired
	private UserInfoService userService;
	
	@Autowired
	private DeptInfoService deptService;
	
	@Autowired
	private RoleInfoService roleInfoService;
	
	@Autowired
	private UserCredentialInfoService userCredentialInfoService;
	
	@Value("${sso.url.success}")
	private String loginSuccessUrl;
	
	@SecurityChecker("user:userInfo:search")
	@RequestMapping("/showList")
	public String showList(ModelMap model) {
		//给定页面能够选择的组织机构树
		SSOUser user = SSOClientUtils.getInstance().findCurrentUser();
		List<Map<String , Object>> deptList = deptService.queryDeptTreeData(user.getTenantNo(), user.getCurrentDept() != null ?user.getCurrentDept().getDeptCode():null 
				, SSOClientUtils.getInstance().isAdmin() , false);
		JsonSerializer serializer = JsonSerializerFactory.findSerializer();
		model.put("treeData", serializer.serialize(deptList));
//		model.put("treeData", JSON.toJSONString(deptList));
		return "user-app/userInfo/list";
	}

	@SecurityChecker("user:userInfo:search")
	@RequestMapping("/search")
	@ResponseBody
	public ApiBaseResponse<PageInfo> search(UserInfoQueryModel user, PageInfo page) {
		if (page == null) {
			page = new PageInfo<UserInfoVO>();
		}
		SSOUser ssoUser = SSOClientUtils.getInstance().findCurrentUser();
		// 非超级管理员，限定默认查询当前用户所在机构下及其下级下的用户
		if (!SSOClientUtils.getInstance().isAdmin() && user.getDeptCode() == null) {
			user.setDeptCode(new String[] {ssoUser.getCurrentDept().getDeptCode()});
		}
		//这边page里面返回的是接口里面声明的UserInfoVO对象
		userService.selectUserVOListByPage(user, page);
		//调用数据翻译,把租户号翻译为对应的租户记录
		List<Map> list = DataTranslateUtils.translate(page.getData(), "tenantCode", "tenant", new TenantTranslateCallback());
		page.setData(list);
		//输出页面
		return new ApiBaseResponse<PageInfo>( RetStatusEnum.SUCCESS,Constants.API_RESPONSE_SUCCESS_CODE,
				Constants.API_RESPONSE_SUCCESS_MESSAGE, page);
	}

	/**
	 * 新增用户
	 */
	@SecurityChecker("user:userInfo:add")
	@RequestMapping("/addPre")
	public String add(ModelMap model) {
		RoleInfoQueryModel query = new RoleInfoQueryModel();
		//给定页面能够选择的组织机构树
		SSOUser user = SSOClientUtils.getInstance().findCurrentUser();
		List<Map<String , Object>> deptList = deptService.queryDeptTreeData(user.getTenantNo(), user.getCurrentDept() != null ?user.getCurrentDept().getDeptCode():null 
				, SSOClientUtils.getInstance().isAdmin(),false);
		JsonSerializer serializer = JsonSerializerFactory.findSerializer();
		model.put("treeData", serializer.serialize(deptList));
//		model.put("treeData", JSON.toJSONString(deptList));
		
		query.setTenantCode(user.getTenantNo());
		model.put("roles", roleInfoService.selectRoleList(query));
		return "user-app/userInfo/add";
	}
	
	/**
	 * 新增保存用户
	 */
	@SecurityChecker("user:userInfo:add")
	@RequestMapping("/add")
	@ResponseBody
	@OperLog(functionName="新增",menuName="用户管理")
	public ApiBaseResponse<Boolean> addSave(UserInfo user , String[] roleIds) {
		// 密码不在指定范围
		if (user.getPassword().length() < 5 || user.getPassword().length() > 18) {
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL, Constants.API_RESPONSE_FAIL_CODE, 
					"密码长度在 5~18 位" , false);
        }

        // 根据组织机构查询租户
        DeptInfo dept = deptService.selectDeptByCode(user.getDeptCode());
        if (null == dept || StringUtils.isBlank(dept.getTenantCode())) {
        	logger.error("find dept by id : {}, dept : {}", new Object[]{user.getDeptCode(), dept});
        	return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE,  "信息异常",false);
        }
        
        user.setTenantCode(dept.getTenantCode());
		try {
			userService.insertUser(user,Arrays.asList(roleIds));
		} catch (Exception e) {
			logger.error("insert user info error ", e);
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL, Constants.API_RESPONSE_FAIL_CODE, 
					Constants.API_RESPONSE_FAIL_MESSAGE,false);
		}
		
		return new ApiBaseResponse<Boolean>(RetStatusEnum.SUCCESS, Constants.API_RESPONSE_SUCCESS_CODE, 
				Constants.API_RESPONSE_SUCCESS_MESSAGE,true);
	}

	/**
	 * 修改用户
	 */
	@RequestMapping("/editPre")
	public String edit(ModelMap model, String id) {
		UserInfo userInfo = userService.selectUserDetailsById(id);
		model.put("user", userInfo);
		SSOUser user = SSOClientUtils.getInstance().findCurrentUser();
		List<Map<String , Object>> deptList = deptService.queryDeptTreeData(userInfo.getTenantCode(), user.getCurrentDept() != null ?user.getCurrentDept().getDeptCode():null, false,false);
		JsonSerializer serializer = JsonSerializerFactory.findSerializer();
		model.put("treeData", serializer.serialize(deptList));
//		model.put("treeData", JSON.toJSONString(deptList));
		
		RoleInfoQueryModel query = new RoleInfoQueryModel();
		query.setTenantCode(user.getTenantNo());
		List<RoleInfo> roleList = roleInfoService.selectRoleList(query); 
		List<String> userRoleList = roleInfoService.findRoleIdByUser(userInfo.getId());
		
		model.put("roles", mergeRole(roleList , userRoleList));
		
		return "user-app/userInfo/edit";
	}
	
	private List<Map<String , Object>> mergeRole(List<RoleInfo> roleList , List<String> userRoleList){
		List<Map<String , Object>> result = new ArrayList<Map<String , Object>>();
		if(roleList != null && roleList.size()>0){
			for(RoleInfo roleInfo : roleList){
				Map<String , Object> item = new HashMap<String , Object>();
				item.put("roleKey", roleInfo.getRoleKey());
				item.put("id", roleInfo.getId());
				item.put("roleName", roleInfo.getRoleName());
				if(userRoleList != null && userRoleList.size()>0){
					if(userRoleList.contains(roleInfo.getId())){
						item.put("selected", true);
					}
				}
				result.add(item);
			}
		}
		return result;
	} 

	/**
	 * 修改保存用户
	 */
	@SecurityChecker("user:userInfo:edit")
	@RequestMapping("/edit")
	@ResponseBody
	@OperLog(functionName="修改",menuName="用户管理")
	public ApiBaseResponse<Boolean> editSave(UserInfo user , String[] roleIds) {
		String rspCode = Constants.API_RESPONSE_SUCCESS_CODE;
		RetStatusEnum rspStatus = RetStatusEnum.SUCCESS;
		String rspMsg = Constants.API_RESPONSE_SUCCESS_MESSAGE;
		if ("admin".equalsIgnoreCase(user.getLoginName())) {
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "不能修改超级管理员" , false);
		}
		try {
			user.setUpdateBy(SSOClientUtils.getInstance().findCurrentUser().getUserName());
			userService.updateUser(user,Arrays.asList(roleIds));
		} catch (Exception e) {
			logger.error("update user info exception ", e);
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "修改用户信息报错" , false);
		}
		return new ApiBaseResponse<Boolean>(rspStatus,rspCode, rspMsg,true);
	}

	@RequestMapping("/modifyPasswdPre")
	public String modifyPasswdPre(ModelMap model, String id) {
		SSOUser loginUser = SSOClientUtils.getInstance().findCurrentUser();
		model.put("user", loginUser);
		return "user-app/userInfo/modifyPasswd";
	}
	
	@RequestMapping("/modifyPasswd")
	@ResponseBody
	@OperLog(functionName="修改密码",menuName="用户管理")
	public ApiBaseResponse<Boolean> modifyPasswd(UpdatePasswordModel updateUser) {
		try {
			if (StringUtils.isBlank(updateUser.getId())) {
				logger.error("Param id must not be blank, param : {}", updateUser);
				return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "用户ID不能为空" , false);
//				throw new IllegalParamException("用户ID不能为空");
			}
			// 登录用户自身重置密码，需要输入原密码并校验，管理员重置密码直接重置即可，这里不对管理员作权限认证
			if (StringUtils.isBlank(updateUser.getOldPassword())) {
				logger.warn("Param oldPassword must not be blank, param : {}", updateUser);
				return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "密码不能为空" , false);
//					throw new IllegalParamException(ExceptionConstants.NULL_OLD_PASSWORD_EXCEPTION_MESSAGE);
			}
			ApiBaseResponse<UserInfo> checkResult = userService.checkUserPasswd(updateUser.getId(), updateUser.getOldPassword());
			if (checkResult.getStatus() != RetStatusEnum.SUCCESS) {
				return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "密码不正确" , false);
//					throw new IllegalParamException(ExceptionConstants.OLD_PASSWORD_ERROR_EXCEPTION_MESSAGE);
			}
			
			userService.changePassword(updateUser.getId(), updateUser.getConfirmNewPassword());
		} catch (Exception e) {
			logger.error("resetPwdSave exception ", e);
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "更新密码异常" , false);
		}
		
		return new ApiBaseResponse<Boolean>(RetStatusEnum.SUCCESS,Constants.API_RESPONSE_SUCCESS_CODE, Constants.API_RESPONSE_SUCCESS_MESSAGE , true);
	}
	
	private static final String FIX_PASSWD = "admin123";
	@SecurityChecker("user:userInfo:resetPwd")
	@RequestMapping("/resetPwd")
	@ResponseBody
	@OperLog(functionName="重置密码",menuName="用户管理")
	public ApiBaseResponse<Boolean> resetPwdSave(String id) {
		try {
			userService.changePassword(id, FIX_PASSWD);
		} catch (Exception e) {
			logger.error("resetPwdSave exception ", e);
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "重置密码异常" , false);
		}
		
		return new ApiBaseResponse<Boolean>(RetStatusEnum.SUCCESS,Constants.API_RESPONSE_SUCCESS_CODE, "密码已重置" , true);
	}

	@SecurityChecker("user:userInfo:remove")
	@RequestMapping("/remove")
	@ResponseBody
	@OperLog(functionName="删除",menuName="用户管理")
	public ApiBaseResponse<Boolean> remove(String ids) {
		SSOUser user = SSOClientUtils.getInstance().findCurrentUser();
		if (Arrays.asList(ids.split(",")).contains(user.getUserId())) {
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "当前用户不允许删除", false);
		}
		try {
			userService.deleteUserByIds(Arrays.asList(ids.trim().split(",")));
		} catch (Exception e) {
			logger.error("delete user info exception ", e);
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "删除用户异常", false);
		}
		return new ApiBaseResponse<Boolean>(RetStatusEnum.SUCCESS, Constants.API_RESPONSE_SUCCESS_CODE, Constants.API_RESPONSE_SUCCESS_MESSAGE,true);
	}

	/**
	 * 校验用户名
	 */
	@RequestMapping("/checkLoginNameUnique")
	@ResponseBody
	public ApiBaseResponse<Boolean> checkLoginNameUnique(UserInfo user) {
		return new ApiBaseResponse<Boolean>(RetStatusEnum.SUCCESS,Constants.API_RESPONSE_SUCCESS_CODE, 
				Constants.API_RESPONSE_SUCCESS_MESSAGE, userService.checkLoginNameUnique(user));
	}

	/**
	 * 校验手机号码
	 */
	@RequestMapping("/checkPhoneUnique")
	@ResponseBody
	public ApiBaseResponse<Boolean> checkPhoneUnique(UserInfo user) {
		return new ApiBaseResponse<Boolean>(RetStatusEnum.SUCCESS,Constants.API_RESPONSE_SUCCESS_CODE, 
				Constants.API_RESPONSE_SUCCESS_MESSAGE, userService.checkPhoneUnique(user));
	}

	/**
	 * 校验email邮箱
	 */
	@RequestMapping("/checkEmailUnique")
	@ResponseBody
	public ApiBaseResponse<Boolean> checkEmailUnique(UserInfo user) {
		return new ApiBaseResponse<Boolean>(RetStatusEnum.SUCCESS,Constants.API_RESPONSE_SUCCESS_CODE, 
				Constants.API_RESPONSE_SUCCESS_MESSAGE, userService.checkEmailUnique(user));
	}

	/**
	 * 用户状态修改
	 */
	@SecurityChecker("user:userInfo:edit")
	@RequestMapping("/changeStatus")
	@ResponseBody
	@OperLog(functionName="修改状态",menuName="用户管理")
	public ApiBaseResponse<Boolean> changeStatus(UserInfo user) {
		if (SSOClientUtils.getInstance().isAdmin()) {
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "管理员的信息不能修改", false);
		}
		// 实际更新了标识为失效/锁定
		try {
			userService.updateUserStatus(user.getId() , user.getStatus() , SSOClientUtils.getInstance().findCurrentUser().getUserName());
		} catch (Exception e) {
			logger.error("update role info error ", e);
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE, "修改状态异常", false);
		}
		return new ApiBaseResponse<Boolean>(RetStatusEnum.SUCCESS,Constants.API_RESPONSE_SUCCESS_CODE,  Constants.API_RESPONSE_SUCCESS_MESSAGE , true);
	}
	
	@RequestMapping("/addCredentialPre")
	public String addCredentialPre(ModelMap model , String id) {
		UserInfo userInfo = userService.selectUserDetailsById(id);
		model.put("user", userInfo);
		DeptInfo deptInfo = deptService.selectDeptByCode(userInfo.getDeptCode());
		model.put("userDept", deptInfo);
		
		SSOUser user = SSOClientUtils.getInstance().findCurrentUser();
		List<Map<String , Object>> deptList = deptService.queryDeptTreeData(userInfo.getTenantCode(), user.getCurrentDept() != null ?user.getCurrentDept().getDeptCode():null
				, SSOClientUtils.getInstance().isAdmin(),false);
		JsonSerializer serializer = JsonSerializerFactory.findSerializer();
		model.put("treeData", serializer.serialize(deptList));
		
		RoleInfoQueryModel query = new RoleInfoQueryModel();
		query.setTenantCode(user.getTenantNo());
		List<RoleInfo> roleList = roleInfoService.selectRoleList(query); 
		List<String> userRoleList = roleInfoService.findRoleIdByUser(userInfo.getId());
		
		model.put("roles", mergeRole(roleList , userRoleList));
		
		return "user-app/userInfo/addCredential";
	}
	
	@RequestMapping("/saveCredential")
	@ResponseBody
	@OperLog(functionName="新增身份",menuName="用户管理")
	@SecurityChecker("user:userInfo:credential")
	public ApiBaseResponse<Boolean> saveCredential(CredentialEditVO edit){
		
		if(edit == null) {
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE,  "输入无效" , false);
		}
		
		if(StringUtils.isBlank(edit.getUserId())) {
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE,  "用户不能为空" , false);
		}
		
		if(StringUtils.isBlank(edit.getDeptCode())) {
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE,  "委派机构不能为空" , false);
		}
		
		if(StringUtils.isBlank(edit.getRoleIds())) {
			return new ApiBaseResponse<Boolean>(RetStatusEnum.FAIL,Constants.API_RESPONSE_FAIL_CODE,  "委派角色不能为空" , false);
		}
		
		edit.setType(Enums.getInstance().getEnumsValueByCode("CREDENTIAL_TYPE", "CREDENTIAL_TYPE_OUTTER"));
		userCredentialInfoService.saveUserCredential(edit);
		return new ApiBaseResponse<Boolean>(RetStatusEnum.SUCCESS,Constants.API_RESPONSE_SUCCESS_CODE,  Constants.API_RESPONSE_SUCCESS_MESSAGE , true);
	}
}
